#ifndef CNETMSG_H
#define CNETMSG_H

#include <QDataStream>

/**
  * CNetMsg defines the base-class for network messages. This class contains methods to interrogate the type of message,
  * as well as a static method to create a message given an input stream.
  *
  * The tNetMsgType enum defines a list of numeric Ids that are used in the message data streams to identify the message
  * type - each Id has a corrosponding base class which will be created in getMsg().
  *
  * Regarding network message format. The format is largely internal, but the first two bytes will always be:
  * 1) 1 unsugned byte representing protocol version number.
  * 2) 1 unsigned byte representing message type.
  *
  * After that the message format is up to the message classes in question,  and will change from version to version.
  *
  */

class CNetMsg
{
public:
	enum tNetMsgType
	{
	MSG_TYPE_CONNECT =0,	    // connection message, client -> server - CConnectMsg
	MSG_TYPE_CONNECT_REPLY =1,  // connection reply message, server -> client - CConnectReplyMsg
	MSG_TYPE_SOURCE =2,			// source message - send source and config to server.
	MSG_TYPE_PROC_UPDATE =3,	// process update message. Sent from server to client.
	MSG_TYPE_RESULTS =4,		// results message. Send from server to client.
	};

	// get this message's type:
	tNetMsgType getType() const;

	// get the current protocol version number. If client and server are using different protocol version
	// numbers then the client connection will be refused:
	static quint8 getProtocolVersion();

	// call this with a QDataStream to get a network message - this will block until a message arrives.
	// the message returned will be one of the CNetMsg derived types - call getType() to determine what
	// the pointer should be casted to.
	//
	// These messages are all created on the heap, so it's the programmers responsibility to delete them once
	// they're finished with.
	// if pErrorStr is set, any errors will populate the QString with a hint as to what went wrong.
	static CNetMsg *getMsg(QDataStream&, QString *pErrorStr =0);

	// call this method to write the message in question to the data stream, in a format that can then be read again by
	// getMsg() above.
	bool setMsg(QDataStream&, QString *pErrorStr =0) const;

protected:
	CNetMsg(tNetMsgType type);
	//
	// All message classes must derive from CNetMsg, and must implement the following methods:

	// serialise the message contents to the data stream.
	virtual void serialiseToStream(QDataStream&) const =0;
	// serialise the message contents from the data stream.
	virtual void serialiseFromStream(QDataStream&) =0;

private:
	tNetMsgType m_nType;	    // store message type
	enum {PROTOCOL_VERSION = 1};    // current protocol version.
};

#endif // CNETMSG_H
